package com.magic.zhixin.service;

import com.github.wxpay.sdk.WXPayConstants;
import com.google.common.collect.Maps;
import com.magic.zhixin.entity.Result;
import com.magic.zhixin.entity.TransferRecord;
import com.magic.zhixin.entity.UserInfo;
import com.magic.zhixin.entity.UserQuestion;
import com.magic.zhixin.model.QuestionStatus;
import com.magic.zhixin.model.TransferType;
import com.magic.zhixin.repository.TransferRecordRepository;
import com.magic.zhixin.repository.UserInfoRepository;
import com.magic.zhixin.repository.UserQuestionRepository;
import com.magic.zhixin.utils.StringUtils;
import com.magic.zhixin.weixin.WeixinPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class WalletService {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private UserInfoRepository userInfoRepository;
    @Autowired
    private WeixinPayUtil weixinPayUtil;
    @Autowired
    private TransferRecordRepository transferRecordRepository;
    @Autowired
    private UserQuestionRepository userQuestionRepository;
    @Value("${weixin.pay.notifyUrl}")
    private String notifyUrl;

    private TransferRecord addTransferRecord(UserInfo userInfo, TransferType transferType, BigDecimal totalAmount, BigDecimal balanceDeduct, String sn, String remark) throws Exception {
//        private String openId; // 微信提现用到openId
//        private String clientIp; // 微信提现用到ip
//        private String paymentNo; // 微信订单号
//        private String paymentTime; // 微信企业付款成功时间

        TransferRecord transferRecord = new TransferRecord();
        transferRecord.setUserId(userInfo.getId());
        transferRecord.setAmount(totalAmount);
        transferRecord.setBalanceDeduct(balanceDeduct);
        transferRecord.setRemark(remark);
        transferRecord.setTradeNo(sn);
        if (totalAmount.subtract(balanceDeduct).compareTo(BigDecimal.ZERO) > 0) {
            transferRecord.setStatus(1);
        } else {
            transferRecord.setStatus(2);
        }

        transferRecord.setTransferType(transferType);
        if (transferType.getType() == TransferType.BALANCE_WITHDRAW.getType()) {
            transferRecord.setOpenId(userInfo.getOpenId());
            transferRecord.setClientIp(getLocalHostLANAddress().getHostAddress());
        }
        transferRecord = transferRecordRepository.save(transferRecord);
        log.info("小程序转账记录,transferRecord{}", transferRecord);
        return transferRecord;
    }

    @Transactional(rollbackFor = Exception.class)
    public Map transfer(Long fUserId, String sn, BigDecimal amount, TransferType transferType) throws Exception {
        UserInfo userInfo = userInfoRepository.findByIdIs(fUserId);
        BigDecimal balance = userInfo.getBalance();
        if (transferType.getType() == TransferType.PAY_HONGBAO_QUESTION.getType()) {
            //支付
            if (balance != null && balance.compareTo(BigDecimal.ZERO) > 0) {
                //优先扣除余额
                if (balance.compareTo(amount) >= 0) {
                    userInfo.setBalance(balance.subtract(amount));
                    userInfoRepository.save(userInfo);
                    //添加转账记录
                    addTransferRecord(userInfo, TransferType.PAY_HONGBAO_QUESTION, amount, amount, sn, "红包问题支付");
                    return Maps.newHashMap();
                } else {
                    userInfo.setBalance(BigDecimal.ZERO);
                    userInfoRepository.save(userInfo);
                    addTransferRecord(userInfo, TransferType.PAY_HONGBAO_QUESTION, amount, balance, sn, "红包问题支付");
                    //发起微信支付
                    Map resp = weixinPayUtil.unifiedOrder(sn, amount.subtract(balance).multiply(new BigDecimal(100)).intValue(), userInfo.getOpenId(), notifyUrl);
                    return resp;
                }
            } else {
                addTransferRecord(userInfo, TransferType.PAY_HONGBAO_QUESTION, amount, BigDecimal.ZERO, sn, "红包问题支付");
                Map resp = weixinPayUtil.unifiedOrder(sn, amount.multiply(new BigDecimal(100)).intValue(), userInfo.getOpenId(), notifyUrl);
                return resp;
            }
        }

        if (transferType.getType() == TransferType.GET_HONGBAO_QUESTUON.getType()) {
            //答题中将
            userInfo.setBalance(balance.add(amount));
            userInfoRepository.save(userInfo);
            addTransferRecord(userInfo, transferType, amount, BigDecimal.ZERO, sn, "答题中奖记录");
        }

        if (transferType.getType() == TransferType.BALANCE_WITHDRAW.getType()) {

            //余额提现

            Map respMap = weixinPayUtil.transfer(userInfo.getId(), amount.multiply(new BigDecimal(100)).intValue(), sn, userInfo.getOpenId(),
                    getLocalHostLANAddress().getHostAddress(), "NO_CHECK", "余额提现");

            if (respMap.get("result_code").equals(WXPayConstants.SUCCESS) && respMap.get("return_code").equals(WXPayConstants.SUCCESS)) {
                TransferRecord transferRecord = addTransferRecord(userInfo, TransferType.BALANCE_WITHDRAW, amount, BigDecimal.ZERO, sn, "余额提现");
                userInfo.setBalance(userInfo.getBalance().subtract(amount));
                userInfoRepository.save(userInfo);
                transferRecord.setStatus(2);
                transferRecordRepository.save(transferRecord);
            }
            logger.error("respMap:" + StringUtils.printMap(respMap));
            return respMap;
        }
        return null;
    }

    public Result<TransferRecord> getAllTransferRecord(UserInfo userInfo) {
        List<TransferRecord> transferRecords = transferRecordRepository.findByStatusAndUserId(2, userInfo.getId());
        return Result.OkResult(transferRecords);
    }

    public UserQuestion findUserQuestionBySn(String sn) {
        return userQuestionRepository.findBySn(sn);
    }

    @Transactional
    public void success(UserQuestion userQuestion, String sn) {
        userQuestion.setQuestionStatus(QuestionStatus.SUCCESS);
        userQuestionRepository.save(userQuestion);

        TransferRecord transferRecord = transferRecordRepository.findByTradeNo(sn);
        transferRecord.setStatus(2);
        transferRecordRepository.save(transferRecord);
    }

    public void fail(UserQuestion userQuestion, String sn) {
        userQuestion.setQuestionStatus(QuestionStatus.FAIL);
        userQuestionRepository.save(userQuestion);

        TransferRecord transferRecord = transferRecordRepository.findByTradeNo(sn);
        transferRecord.setStatus(3);
        transferRecordRepository.save(transferRecord);

        if (transferRecord.getBalanceDeduct().compareTo(BigDecimal.ZERO) > 0) {
            //余额回退
            UserInfo userInfo = userInfoRepository.findByIdIs(transferRecord.getUserId());
            userInfo.setBalance(userInfo.getBalance().add(transferRecord.getBalanceDeduct()));
            userInfoRepository.save(userInfo);
        }
    }


    public UserInfo getBalance(UserInfo userInfo) {
        return userInfoRepository.findByIdIs(userInfo.getId());
    }

    private InetAddress getLocalHostLANAddress() throws Exception {
        try {
            InetAddress candidateAddress = null;
            // 遍历所有的网络接口
            for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) {
                NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
                // 在所有的接口下再遍历IP
                for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) {
                    InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
                    if (!inetAddr.isLoopbackAddress()) {// 排除loopback类型地址
                        if (inetAddr.isSiteLocalAddress()) {
                            // 如果是site-local地址，就是它了
                            return inetAddr;
                        } else if (candidateAddress == null) {
                            // site-local类型的地址未被发现，先记录候选地址
                            candidateAddress = inetAddr;
                        }
                    }
                }
            }
            if (candidateAddress != null) {
                return candidateAddress;
            }
            // 如果没有发现 non-loopback地址.只能用最次选的方案
            InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
            return jdkSuppliedAddress;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
